#!/usr/bin/perl -w

#=======================================================================
# $Id$
# Converts Subversion/RCS/CVS keywords in text files in various ways. 
# Optimised for use with Subversion at the moment, but also works with 
# CVS and RCS.
#
# Character set: UTF-8
# License: GNU General Public License
# Author: Øyvind A. Holm <sunny@sunbase.org>
# This file is part of the svnutils package — http://svnutils.tigris.org
#=======================================================================

use strict;
use Getopt::Std;

our ($opt_c, $opt_D, $opt_h, $opt_S, $opt_s, $opt_V) =
    (     0,      0,      0,      0,      0,      0);
getopts('cDhSsV') || die("Option error, use -h for help");

my $rcs_id = '$Id$';
my $stripped_rcs_id = $rcs_id;
$stripped_rcs_id =~ s/^\$(.*)\s+\S+\s+\$$/$1/;

$| = 1;

my @Keywords = (
                "Id",
                "Author", "LastChangedBy",
                "Date", "LastChangedDate",
                "LastChangedRevision", "Revision", "Rev",
                "URL", "HeadURL",
                "Header",
                "Name",
                "Locker",
                "Log",
                "RCSfile",
                "Source",
                "State"
               );
my $Keyw = join('|', @Keywords); # Used in regexps

$opt_h && usage(0);

$opt_s && $opt_S && die("convkeyw: Cannot mix the -s and -S option.\n");

if ($opt_V) {
    print("$stripped_rcs_id\n");
    exit(0);
}

my $rand_ext = "$$." . substr(rand, 2, 8);
while (defined($ARGV[0])) {
    # Scan through all file names on the command line {{{
    my $Curr = shift;
    my $Dest = "$Curr.$rand_ext.tmp";
    if (open(FromFP, $Curr)) {
        (-e $Dest) && die("$Dest: What??? File already exists!");
        if (open(ToFP, ">$Dest")) {
            while (<FromFP>) {
                /\$/ && ($_ = process_line($_));
                print(ToFP $_);
            }
            close(FromFP);
            close(ToFP);
            rename($Dest, $Curr) || warn("rename($Dest, $Curr): $!");
        } else {
            warn("$Dest: Unable to create file: $!");
        }
    } else {
        warn("$Curr: Unable to open file for read: $!");
    }
    # }}}
}

sub process_line {
    # {{{
    my $Retval = shift;

    if ($opt_c) {
        # Compress all keywords
        $Retval =~ s/(\$)($Keyw): .*? (\$)/$1$2$3/;
    }

    if ($opt_D) {
        # Remove the () stuff from the Subversion $Date.
        $Retval =~ s/(\$Date: .*?)\(..., \d+ ... \d\d\d\d\) (\$)/$1$2/g;
    }

    if ($opt_s) {
        # Strip keywords — remove dollars, keyword and colon. This 
        # action is destructive and has to be last.
        $Retval =~ s/\$($Keyw): (.*?) \$/$2/g;
        $Retval =~ s/\$($Keyw)\$/$1/g;
    } elsif ($opt_S) {
        # Strip keywords — remove dollars only. This action is 
        # destructive and has to be last.
        $Retval =~ s/\$($Keyw): (.*?) \$/$1: $2/g;
        $Retval =~ s/\$($Keyw)\$/$1/g;
    }

    return($Retval);
    # }}}
}

sub usage {
    # Send help text to stdout {{{
    my $Retval = shift;
    print <<END;

Syntax: convkeyw [options] file [file [...]]

Convert RCS/CVS/Subversion keywords in text files in various ways.

Options:

    -c  Compress keywords in the file, for example:
            \$Id: dbk 963 2004-09-29 08:14:15Z sunny \$
          is changed to
            \$Id\$
        This can be useful when comparing files against the text-base.
    -D  Remove the long date format from Subversion \$Id\$ strings.
            \$Date: 2004-05-18 10:44:54 +0200 (Tue, 18 May 2004) \$
          is changed to
            \$Date: 2004-05-18 10:44:54 +0200 \$
    -h  Print this help.
    -s  Strip keywords, i.e. remove the " \$", "\$Id: :" and "\$Date: " 
        from keywords to protect them from changes when importing or 
        adding the file to a new repository.
            \$Id: file.txt 123 2004-01-21 17:12:16Z fjodor \$
          is changed to
            file.txt 123 2004-01-21 17:12:16Z fjodor
        WARNING: After using this option, further processing of keywords 
        in the file is impossible. Meant for use in tarballs and 
        releases.
    -S  Strip dollars from keywords like -s, but leave the keyword 
        itself and the colon intact. I.e.:
            \$Id: file.txt 123 2004-01-21 17:12:16Z fjodor \$
          is changed to
            Id: file.txt 123 2004-01-21 17:12:16Z fjodor
    -V  Print version of the script:
          $stripped_rcs_id

END
    # }}}
    exit($Retval);
}

__END__

# vim: set et ts=4 sw=4 sts=4 fo+=w fo+=c fo-=t tw=72 :
# End of file $Id$
